package com.lantosec.hmrp.modules.workflow.listener;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lantosec.hmrp.core.exception.AppException;
import com.lantosec.hmrp.core.kit.Result;
import com.lantosec.hmrp.core.kit.ResultEnum;
import com.lantosec.hmrp.modules.form.mapper.FormColumnsMapper;
import com.lantosec.hmrp.modules.form.service.IFormService;
import com.lantosec.hmrp.modules.sysdata.entity.SysProcessForm;
import com.lantosec.hmrp.modules.sysdata.service.ISysProcessFormService;
import com.lantosec.hmrp.modules.system.service.ISysUserService;
import com.lantosec.hmrp.modules.system.service.ISysWorkdayService;
import com.lantosec.hmrp.modules.workflow.enumeration.ProcessVariableEnum;
import com.lantosec.hmrp.modules.workflow.service.IWorkflowRepositoryService;
import com.lantosec.hmrp.modules.workflow.service.IWorkflowRuntimeService;
import com.lantosec.hmrp.modules.workflow.vo.SaveProcessTaskVO;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.FieldExtension;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Objects;


/**
 * 子流程开始监听事件
 *
 * @author lichaowei
 * @date 2020/5/26
 */
@Component
@Log4j2
public class CallActivityStartListener implements ExecutionListener {
    private static final long serialVersionUID = 1L;

    @Autowired
    ISysUserService sysUserService;
    @Autowired
    ISysWorkdayService workdayService;
    @Autowired
    IWorkflowRuntimeService workflowRuntimeService;
    @Autowired
    IWorkflowRepositoryService workflowRepositoryService;
    @Autowired
    private ISysProcessFormService sysProcessFormService;
    @Autowired
    private FormColumnsMapper formColumnsMapper;
    @Autowired
    private IFormService formService;

    @Override
    public void notify(DelegateExecution delegateExecution) {
        String processInstanceId = delegateExecution.getProcessInstanceId();
        String processDefinitionId = delegateExecution.getProcessDefinitionId();
        log.info("子流程开始监听事件----->processInstanceId:" + processInstanceId);

        List<FieldExtension> fieldExtensionList = delegateExecution.getCurrentFlowableListener().getFieldExtensions();
        if(CollectionUtils.isEmpty(fieldExtensionList)){
            throw new AppException("没有配置子流程数据源的SQL");
        }
        // 暂时只有一个参数，callActivitySql
        String callActivitySql = fieldExtensionList.get(0).getStringValue();

        //获取流程变量
        JSONObject dataJson = (JSONObject) delegateExecution.getVariable(ProcessVariableEnum.BUSINESS_DATA.getCode());
        SysProcessForm sysProcessForm = sysProcessFormService.selectByDefinitionId(processDefinitionId);
        if (Objects.isNull(sysProcessForm)) {
            throw new AppException("查询流程定义与表单的关系失败");
        }

        if (StringUtils.isNotEmpty(callActivitySql)) {
            String formDataId = insertData(callActivitySql, sysProcessForm.getFormTableId(), dataJson);
            //子流程实例set业务单号，这里设置无效，在ProcessStartListener里面设置
            //runtimeService.updateBusinessKey(processInstanceId, formDataId);
            delegateExecution.setVariable(ProcessVariableEnum.BUSINESS_KEY.getCode(), formDataId);
        }

    }

    /**
     * 保存子流程的数据
     * @return
     */
    private String insertData(String sql, String subFormTableId, JSONObject dataJson) {
        // 参数替换
        sql = com.lantosec.hmrp.core.util.StringUtils.processTemplate(sql, dataJson);
        // 查询数据
        List<Map<String, Object>> list = formColumnsMapper.executeSelectSql(sql);
        if (CollectionUtils.isNotEmpty(list)) {
            Map<String, Object> dataMap = list.get(0);
            SaveProcessTaskVO saveVO = new SaveProcessTaskVO();
            saveVO.setFormData(JSON.toJSONString(dataMap));
            saveVO.setFormTableId(subFormTableId);
            // 保存数据到子流程的表单
            Result<String> formResult = formService.save(saveVO);
            if (!ResultEnum.SUCCESS.code.equals(formResult.getState())) {
                Result.fail(formResult.getMessage());
            }
            return formResult.getData();
        }
        return "";
    }

}
